﻿using System;
using System.Threading;
using FluentPS.WebSvcQueueSystem;

namespace FluentPS.Services.Impl
{
    public class PSQueueSystemService : IPSQueueSystemService
    {
        public const string WebServiceUrl = "QueueSystem.asmx";

        private readonly ISessionService _sessionService;
        private readonly QueueSystem _wssQueueSystem;
        private readonly ILogService _logService;

        public const int DefaultWaitDelay = 2; // in sec
        public const int DefaultAttemptsMax = 5;

        public PSQueueSystemService(ILogService logService, ISessionService sessionService)
        {
            _sessionService = sessionService;
            _logService = logService;

            _wssQueueSystem = new QueueSystem();
            Init();
        }

        private void Init()
        {
            _wssQueueSystem.Url = _sessionService.PsiBaseUrl + WebServiceUrl;
            _wssQueueSystem.UseDefaultCredentials = true;
        }

        public bool WaitForQueue(Guid jobId)
        {
            return WaitForQueue(jobId, TimeSpan.FromSeconds(DefaultWaitDelay), DefaultAttemptsMax);
        }

        public bool WaitForQueue(Guid jobId, TimeSpan waitDelay, int attemptsMax)
        {
            string xmlError = string.Empty;
            int wait = 0;
            int attemptsCount = 0;
            wait = _wssQueueSystem.GetJobWaitTime(jobId);

            Thread.Sleep(wait * 1000);
            do
            {
                JobState jobState = _wssQueueSystem.GetJobCompletionState(jobId, out xmlError);

                if (jobState == JobState.Success)
                {
                    return true;
                }
                else
                {
                    if (jobState == JobState.Unknown
                        || jobState == JobState.Failed
                        || jobState == JobState.FailedNotBlocking
                        || jobState == JobState.CorrelationBlocked
                        || jobState == JobState.Canceled)
                    {
                        _logService.Log("Queue request " + jobState + " for Job ID " + jobId + ".\r\n" + xmlError);
                        return false;
                    }
                }

                attemptsCount++;
                Thread.Sleep(waitDelay);
            }
            while (attemptsCount > attemptsMax);

            return false;
        }

        public void CancelJob(Guid jobUid)
        {
            _wssQueueSystem.CancelJobSimple(jobUid);
        }
    }
}
